#!/bin/bash

OSC_PORT_MIN=31338 # include
OSC_PORT_MAX=31438 # NOT include

#MYCOPROC="mycoproc$$"
#eval $(echo "coproc $MYCOPROC { nc localhost $OSC_PORT; }")
#eval $(echo "MYOUTPUT=\${$MYCOPROC[0]}")
#eval $(echo "MYINPUT=\${$MYCOPROC[1]}")
#echo  $MYCOPROC
#trap int_cleanup INT

int_cleanup() {
    cleanup_osc
}

# $1 main process ? 
# $2 $3 ... openstack options
init_osc() {
    local try=6
    local master=$1
    shift

    MYCOPROC="mycoproc$$"

    if $master; then
        OSC_PORT=$OSC_PORT_MIN
        while((OSC_PORT < OSC_PORT_MAX)); do
            ss -4lnt |awk '{print $4}' |grep -w $OSC_PORT &>/dev/null
            [ $? -eq 0 ] && { ((OSC_PORT ++)); continue; } || break
        done
        if ((OSC_PORT == OSC_PORT_MAX)); then
            echo "failed to init fast osc: no port available." >&1
            return 1
        fi

        # maybe fail when port already in use
        /bin/bash -c "timeout 1800 /usr/bin/nc -e \"/usr/bin/stdbuf -o0 /opt/ansible/bin/openstack $*\" -klp$OSC_PORT &"
        NCPID=$!
        while true; do
          ss -4lnt |awk '{print $4}' |grep -w $OSC_PORT &>/dev/null
          if [ $? -eq 0 ];then
                NCPID=$(ss -4lntp|grep -w $OSC_PORT|sed  's/.*pid=\([0-9]*\).*/\1/')
                break
          fi
          ((try--))
          if [ $try -eq 0 ]; then
              echo "failed to init fast osc: no nc process found." >&1
              return 1
          fi  
          sleep 1
        done
        # share with child processes
        export OSC_PORT
    else # child
        if [ ! -n "$OSC_PORT" ]; then
#            echo "failed to init fast osc: no OSC_PORT found." >&1
            return 1
        fi
    fi
 
#    echo "coproc $MYCOPROC { nc localhost $OSC_PORT; }"
    eval $(echo "coproc $MYCOPROC { nc localhost $OSC_PORT; }")
    [ $? -eq 0 ] || return 1
#    echo "MYOUTPUT=\${$MYCOPROC[0]}"
#    echo "MYINPUT=\${$MYCOPROC[1]}"
    eval $(echo "MYOUTPUT=\${$MYCOPROC[0]}")
    eval $(echo "MYINPUT=\${$MYCOPROC[1]}")
#    echo $MYOUTPUT
#    echo $MYINPUT
}

cleanup_osc() {
#    local t=${MYCOPROC}_PID
#    echo "kill ${!t}"
#    eval $(echo "kill \${${MYCOPROC}_PID}")
    kill $NCPID &>/dev/null
}

run_openstack() {
    local params=$*
    local var=
   
    echo -e "${params}\n--help\n" >&"$MYINPUT"
    [ $? -eq 0 ] || return 1
    while true;do
        read var <&"$MYOUTPUT"
        [ $? -eq 0 ] || { return 2; }
        # openstack: '--help' is not an openstack command. See 'openstack --help'.
        # Did you mean one of these?
        # help
        if [ "${var:0:12}" == "openstack: '" ]; then
            read var <&"$MYOUTPUT"
            read var <&"$MYOUTPUT"
            break
        fi
        echo -e "$var"
#        sleep 1
    done
}

get_instance_by_fip() {
    local fip=$(_parse $1 ip)
    shift
    while read line;do
        echo $line |grep -w $fip |awk '{print $1}'
    done << EOF
$(run_openstack server list --column Networks --column ID -f value)
EOF
}

get_floatingIP() {
    local portid=$1
    shift
    while read line;do
        echo $line |awk '{print $2}'
    done << EOF
$(run_openstack server list --column Networks -f value)
EOF
}

reboot_instance() {
    local vm=$1
    shift
    echo "openstack server reboot --hard $vm"
    run_openstack server reboot --hard $vm
}

rebuild_instance() {
    local vm=$1
    shift
    echo "openstack server rebuild $vm"
    run_openstack server rebuild $vm
}

show_instance() {
    local vm=$1
    shift
    run_openstack server show $vm
    run_openstack console url show $vm
}

get_instance_status() {
    local vm=$1
    shift
    local status=$(run_openstack server show $vm -c status -f value)
    echo $status
}

get_instance_image() {
    local vm=$1
    shift
    while read line;do
        echo $line \
     |sed 's/.*\([0-9a-f]\{8\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{4\}-[0-9a-f]\{12\}\).*/\1/'
    done << EOF
$(run_openstack server show $vm -c image -f value)
EOF
}

get_network_id(){
    local portid=$1
    shift
    while read line;do
        echo $line
    done << EOF
$(run_openstack port show $portid -c network_id -f value)
EOF
}

get_image_os_properties() {
    local image=$1
    shift
    while read line;do
        echo $line
    done << EOF
$(run_openstack image show $image -c properties -f value)
EOF
}

get_image_os_distro() {
    local image=$1
    shift
    while read line;do
        echo -e "try:\n\
 d=$line\n\
 print d['os_distro']\n\
except:\n\
 pass\n\
" |python -
    done << EOF
$(run_openstack image show $image -c properties -f value)
EOF
}

get_port_device_owner() {
    local portid=$1
    shift
    while read line;do
        echo $line
    done << EOF
$(run_openstack port show $portid -c device_owner -f value)
EOF
}

get_port_id() {
    local project=$1
    local fip=$2
    local s=
    shift 2
    [ -n "$project" ] && s="--project $project"
    while read line;do
        echo $line \
           |grep -w $fip |awk '{print $1}'
    done << EOF
$(run_openstack port list -f value $s)
EOF
}

